package com.leyou.search.service.impl;


import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.item.client.ItemClient;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpecParamDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.pojo.Goods;
import com.leyou.repository.GoodRepository;
import com.leyou.search.service.IndexService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: YHL
 * @time: 2021/2/27 21:20
 */
@Service
public class IndexServiceImpl implements IndexService {

    @Autowired
    private GoodRepository goodRepository;

    @Autowired
    private ItemClient itemClient;


    @Override
    public void loadData() {

        Integer page = 1;

        //从数据库取数据，取spu，取上架的spu，把获取到的spu变形到goods，再次保存goods
        while (true) {
            PageDTO<SpuDTO> spuDTOPageDTO = this.itemClient.pageQuery(page, 60, null, null, null, true);

            //总页数为0，表示没有数据
            if (0 == spuDTOPageDTO.getTotalPage()) {
                break;
            }

            //获取数据,把获取到的SpuDTO集合转换为goods集合
            List<Goods> goodsList = spuDTOPageDTO.getItems().stream().map(this::buildGoods).collect(Collectors.toList());

            //批量保存
            this.goodRepository.saveAll(goodsList);

            page++;

            //查询完毕
            if (page > spuDTOPageDTO.getTotalPage()) {
                break;
            }
        }


    }


    @Override
    public void initIndexes() {
        try {
            this.goodRepository.deleteIndex();
        } catch (Exception e) {
        }

        this.goodRepository.createIndex("{\n" +
                "  \"settings\": {\n" +
                "    \"analysis\": {\n" +
                "      \"analyzer\": {\n" +
                "        \"my_pinyin\": {\n" +
                "          \"tokenizer\": \"ik_smart\",\n" +
                "          \"filter\": [\n" +
                "            \"py\"\n" +
                "          ]\n" +
                "        }\n" +
                "      },\n" +
                "      \"filter\": {\n" +
                "        \"py\": {\n" +
                "\t\t  \"type\": \"pinyin\",\n" +
                "          \"keep_full_pinyin\": true,\n" +
                "          \"keep_joined_full_pinyin\": true,\n" +
                "          \"keep_original\": true,\n" +
                "          \"limit_first_letter_length\": 16,\n" +
                "          \"remove_duplicated_term\": true\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  },\n" +
                "  \"mappings\": {\n" +
                "    \"properties\": {\n" +
                "      \"id\": {\n" +
                "        \"type\": \"keyword\"\n" +
                "      },\n" +
                "      \"suggestion\": {\n" +
                "        \"type\": \"completion\",\n" +
                "        \"analyzer\": \"my_pinyin\",\n" +
                "        \"search_analyzer\": \"ik_smart\"\n" +
                "      },\n" +
                "      \"title\":{\n" +
                "        \"type\": \"text\",\n" +
                "        \"analyzer\": \"my_pinyin\",\n" +
                "        \"search_analyzer\": \"ik_smart\"\n" +
                "      },\n" +
                "      \"image\":{\n" +
                "        \"type\": \"keyword\",\n" +
                "        \"index\": false\n" +
                "      },\n" +
                "      \"updateTime\":{\n" +
                "        \"type\": \"date\"\n" +
                "      },\n" +
                "      \"specs\":{\n" +
                "        \"type\": \"nested\",\n" +
                "        \"properties\": {\n" +
                "          \"name\":{\"type\": \"keyword\" },\n" +
                "          \"value\":{\"type\": \"keyword\" }\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}");
    }

    @Override
    public void handleGoodsUp(Long id) {
        //根据spuId查询对应的商品
        PageDTO<SpuDTO> spuDTOPageDTO = this.itemClient.pageQuery(1, 1, id, null, null, true);

        if (spuDTOPageDTO.getTotal() == 1) {

            SpuDTO spuDTO = spuDTOPageDTO.getItems().get(0);

            this.goodRepository.save(this.buildGoods(spuDTO));

        } else {
            throw new LyException(400, "商品id有误，无法找到对应id的商品进行上架处理，id为：" + id);
        }

    }

    @Override
    public void handleGoodsDown(Long id) {

        this.goodRepository.deleteById(id);
    }


    //基于spuDTO构建goods对象
    @Override
    public Goods buildGoods(SpuDTO spuDTO) {

        Goods goods = new Goods();

        BeanUtils.copyProperties(spuDTO, goods);

        //分类id
        goods.setCategoryId(spuDTO.getCid3());

        //根据spuId查询对应sku的集合

        List<SkuDTO> skuDTOS = this.itemClient.listSkuBySpuId(spuDTO.getId());


        //从某个sku中的多个图片中获取一张
        goods.setImage(StringUtils.substringBefore(skuDTOS.get(0).getImages(), ","));


        Set<Long> prices = new HashSet<>();

        Long sold = 0L;
        for (SkuDTO skuDTO : skuDTOS) {
            sold += skuDTO.getSold();
            prices.add(skuDTO.getPrice());
        }

        goods.setSold(sold);
        goods.setPrices(prices);


        goods.setUpdateTime(new Date());

        //根据商品id以及可搜索特征查询所有的可搜索规格参数以及对应的值
        List<SpecParamDTO> specParamDTOS = this.itemClient.listSpecParam(spuDTO.getId(), true);

        //把获取到的结果值封装到list中的map中保存
        List<Map<String, Object>> listSpecMap = new ArrayList<>();
        specParamDTOS.forEach(specParamDTO -> {
            Map<String, Object> specMap = new HashMap<>();
            specMap.put("name", specParamDTO.getName());

            //value赋值要考虑是否要加区间
            specMap.put("value", chooseSegment(specParamDTO));
            listSpecMap.add(specMap);
        });


        //可搜索规格参数
        goods.setSpecs(listSpecMap);

        //商品名称||品牌+分类||分类+品牌||品牌+商品名称

        List<String> suggest = new ArrayList<>();

        suggest.add(spuDTO.getName());

        //如果名称中包含括号，则只取括号之前的内容
        String brandName = StringUtils.substringBefore(spuDTO.getBrandName(), "（");

        //手机/手机通讯/手机
        String categoryName = spuDTO.getCategoryName().split("/")[2];

        suggest.add(brandName + categoryName);

        suggest.add(categoryName + brandName);
        suggest.add(brandName + spuDTO.getName());
        goods.setSuggestion(suggest);


        return goods;
    }


    private Object chooseSegment(SpecParamDTO p) {
        Object value = p.getValue();
        if (value == null || StringUtils.isBlank(value.toString())) {
            return "其它";
        }
        if (!p.getNumeric() || StringUtils.isBlank(p.getSegments()) || value instanceof Collection) {
            return value;
        }
        double val = parseDouble(value.toString());
        String result = "其它";
        // 保存数值段
        for (String segment : p.getSegments().split(",")) {
            String[] segs = segment.split("-");
            // 获取数值范围
            double begin = parseDouble(segs[0]);
            double end = Double.MAX_VALUE;
            if (segs.length == 2) {
                end = parseDouble(segs[1]);
            }
            // 判断是否在范围内
            if (val >= begin && val < end) {
                if (segs.length == 1) {
                    result = segs[0] + p.getUnit() + "以上";
                } else if (begin == 0) {
                    result = segs[1] + p.getUnit() + "以下";
                } else {
                    result = segment + p.getUnit();
                }
                break;
            }
        }
        return result;
    }

    private double parseDouble(String str) {
        try {
            return Double.parseDouble(str);
        } catch (Exception e) {
            return 0;
        }
    }

}

